package com.lcm.weam.controller.algo;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.lcm.weam.entity.algo.GMArchive;
import com.lcm.weam.entity.algo.GMResult;
import com.lcm.weam.entity.algo.MarkovArchive;
import com.lcm.weam.entity.algo.MarkovResult;
import com.lcm.weam.entity.resp.Result;
import com.lcm.weam.entity.resp.ResultCode;
import com.lcm.weam.service.algo.PredictService;
import com.lcm.weam.util.AliOSSUtil;
import com.lcm.weam.util.ExcelHandler;
import com.lcm.weam.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 算法接口
 * 1、基于文件模板的时间序列灰色预测模型
 * 2、基于输入数组的时序灰色预测模型
 * 3、下载灰色预测模型结果excel
 * 4、下载输入数据模板(GM和Markov通用)
 * 5、基于文件模板的加权马尔科夫链模型
 * 6、基于输入数组的加权马尔科夫链模型
 * 7、下载灰色预测模型结果excel
 * 8、gm结果归档
 * 9、markov结果归档
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/algo")
public class PredictController {

    @Autowired
    private PredictService predictService;

    /**
     * GM模型输入为：
     *   double[] data : 原数据
     *   int t : 预测次数
     */

    //1、基于文件模板的时间序列灰色预测模型
//    @Encrypt
    @RequestMapping(value = "/GM/file", method = RequestMethod.POST)
    public Result GM(MultipartFile file, int t) throws IOException {
        if (file.isEmpty()){
            return new Result(ResultCode.FAIL);
        }
        GMResult gmResult = predictService.GM(file, t);
        return new Result(ResultCode.SUCCESS, gmResult);
    }

    //2、基于输入数组的时序灰色预测模型
//    @Encrypt
    @RequestMapping(value = "/GM/arr", method = RequestMethod.POST)
    public Result GM(double[] arr, Integer t) throws IOException {
        if (arr.length <= 0){
            return new Result(ResultCode.FAIL);
        }
        GMResult gmResult = predictService.GM(arr, t);
        return new Result(ResultCode.SUCCESS, gmResult);
    }

    //3、下载灰色预测模型结果excel
    @RequestMapping(value = "/GM/download", method = RequestMethod.POST)
    public void GM(@RequestBody GMResult gmResult, HttpServletResponse response) throws IOException {
        ByteArrayOutputStream outputStream = ExcelHandler.writeGMResult(gmResult);
        AliOSSUtil.download(outputStream, response, UUID.randomUUID().toString() + ".xlsx");
    }

    //获取模板
    @RequestMapping(value = "/getTemplate", method = RequestMethod.GET)
    public void getTemplate(HttpServletResponse response) throws IOException {
        String path = ResourceUtils.getURL("classpath:").getPath() + "public/数据模板.xlsx";
        /* 获取文件的名称 . */
        String fileName = path.substring(path.lastIndexOf("/") +1);
        File file = new File(path);
        /* 将文件名称进行编码 */
        response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
        response.setContentType("content-type:application/octet-stream");
        BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
        OutputStream outputStream = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1){ /* 将流中内容写出去 .*/
            outputStream.write(buffer ,0 , len);
        }
        inputStream.close();
        outputStream.close();
    }

    /**
     * Markov模型输入为：
     *   double[] data : 原数据
     *   int t : 预测次数（迭代次数）
     *   int m : 状态数
     */

    //5、基于文件模板的加权马尔科夫链模型
//    @Encrypt
    @RequestMapping(value = "/Markov/file", method = RequestMethod.POST)
    public Result Markov(MultipartFile file, int n, int t) throws IOException {
        if (file.isEmpty()){
            return new Result(ResultCode.FAIL);
        }
        MarkovResult markov = predictService.Markov(file, n, t);
        return new Result(ResultCode.SUCCESS, markov);
    }

    //6、基于输入数组的加权马尔科夫链模型
//    @Encrypt
    @RequestMapping(value = "/Markov/arr", method = RequestMethod.POST)
    public Result Markov(double[] arr, int n, Integer t) throws IOException {
        if (arr.length <= 0){
            return new Result(ResultCode.FAIL);
        }
        MarkovResult markov = predictService.Markov(arr, n, t);
        return new Result(ResultCode.SUCCESS, markov);
    }

    //7、下载加权马尔科夫链模型结果excel
    @RequestMapping(value = "/Markov/download", method = RequestMethod.POST)
    public void Markov(@RequestBody MarkovResult markovResult, HttpServletResponse response) throws IOException {
        ByteArrayOutputStream outputStream = ExcelHandler.writeMarkovResult(markovResult);
        AliOSSUtil.download(outputStream, response, UUID.randomUUID().toString() + ".xlsx");
    }

    //8、gm数据归档
    @RequestMapping(value = "/GM/archive", method = RequestMethod.POST)
    public Result gmArchive(@RequestBody GMResult gmResult){
        GMArchive gmArchive = new GMArchive();
        String gmJson = JsonUtil.stringify(gmResult);
        gmArchive.setId(IdWorker.getIdStr());
        gmArchive.setGmResult(gmJson);
        gmArchive.setDate(new Date());
        predictService.gmArchive(gmArchive);
        return new Result(ResultCode.SUCCESS);
    }


    //9、gm数据获取
    @RequestMapping(value = "/GM/listAll", method = RequestMethod.POST)
    public Result gmListAll(){
        List<GMArchive> gmList= predictService.gmListAll();
        return new Result(ResultCode.SUCCESS, gmList);
    }

    //10、gm数据根据id删除
    @RequestMapping(value = "/GM/delete", method = RequestMethod.POST)
    public Result gmDelete(String id){
        predictService.gmDelete(id);
        return new Result(ResultCode.SUCCESS);
    }

    //11、markov数据归档
    @RequestMapping(value = "/Markov/archive", method = RequestMethod.POST)
    public Result markovArchive(@RequestBody MarkovResult markovResult){
        MarkovArchive markovArchive = new MarkovArchive();
        String gmJson = JsonUtil.stringify(markovResult);
        markovArchive.setId(IdWorker.getIdStr());
        markovArchive.setMarkovResult(gmJson);
        markovArchive.setDate(new Date());
        predictService.markovArchive(markovArchive);
        return new Result(ResultCode.SUCCESS);
    }


    //12、markov数据获取
    @RequestMapping(value = "/Markov/listAll", method = RequestMethod.POST)
    public Result markovListAll(){
        List<MarkovArchive> markovList= predictService.markovListAll();
        return new Result(ResultCode.SUCCESS, markovList);
    }

    //13、markov数据根据id删除
    @RequestMapping(value = "/Markov/delete", method = RequestMethod.POST)
    public Result markovDelete(String id){
        predictService.markovDelete(id);
        return new Result(ResultCode.SUCCESS);
    }
}
